package view.commonview;

import java.awt.Event;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;

import view.UtilityConstants;
import controller.commoncontroller.AboutLocsiListener;
import controller.commoncontroller.CheckListener;
import controller.commoncontroller.CircuitInfoListener;
import controller.commoncontroller.ComponentExportListener;
import controller.commoncontroller.ComponentImportListener;
import controller.commoncontroller.DeleteSelectionListener;
import controller.commoncontroller.ExitListener;
import controller.commoncontroller.LoadCircuitListener;
import controller.commoncontroller.NewCircuitListener;
import controller.commoncontroller.PictureExportListener;
import controller.commoncontroller.RasterElementsListener;
import controller.commoncontroller.SaveCircuitListener;
import controller.commoncontroller.SelectAllListener;
import controller.commoncontroller.SettingsListener;
import controller.commoncontroller.UserManualListener;
import controller.commoncontroller.ZoomInListener;
import controller.commoncontroller.ZoomOutListener;
import controller.editorcontroller.AutoCreateSwitchListener;
import controller.editorcontroller.AutoCreateLampListener;
import controller.simulationcontroller.ShowTruthTableListener;
import model.editormodel.EditorModel;
import model.simulationmodel.SimulationModel;

/**
 * <b>Erbt:</b> <code>JMenuBar</code> <br>
 * <b>Funktion:</b> Repraesentation der Menueleiste<br>
 * <br>
 * Menueleiste in der die meisten Programmfunktionen aufgefuehrt sind. Bestimmte
 * Funktionen sind im Simulationsmodus ausgeblendet.
 * 
 * @author Team Locsi
 * 
 */
@SuppressWarnings("serial")
public class MenuBar extends JMenuBar {

	private JMenu circuit = new JMenu("Schaltung");
	private JMenu edit = new JMenu("Bearbeiten");
	private JMenu look = new JMenu("Ansicht");
	private JMenu help = new JMenu("Hilfe");

	// JMenuItems fuer den Menuepunkt Schaltung
	// ------------------------------------------------------------------------
	private JMenuItem newC = new JMenuItem("Neu", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "newM.png")));
	private JMenuItem load = new JMenuItem("Laden", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "loadM.png")));
	private JMenuItem save = new JMenuItem("Speichern", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "saveNewM.png")));
	private JMenu export = new JMenu("Exportieren");
	private JMenuItem comp = new JMenuItem("Bauteil", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "bauteilM.png")));
	private JMenuItem png = new JMenuItem("PNG-Datei", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "png.png")));
	private JMenuItem jpeg = new JMenuItem("JPEG-Datei", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "jpeg.png")));
	private JMenuItem gif = new JMenuItem("GIF-Datei", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "gif.png")));
	private JMenuItem bmp = new JMenuItem("BMP-Datei", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "bmp.png")));
	private JMenuItem imp = new JMenuItem("Importieren", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "importM.png")));
	private JMenuItem exit = new JMenuItem("Beenden", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "exitM.png")));
	// ------------------------------------------------------------------------

	// JMenuItems fuer den Menuepunkt Bearbeiten
	// -------------------------------------------------------------------------
	private JMenuItem selectAll = new JMenuItem("Alles markieren",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "selectall.png")));
	private JMenuItem delete = new JMenuItem("Löschen", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "deleteM.png")));
	private JMenuItem check = new JMenuItem("Auf Fehler überprüfen",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "checkNewM.png")));
	// private JMenuItem rasterVisible = new JMenuItem("Raster ein/ausblenden",
	// new ImageIcon(UtilityConstants.ICON_PATH + "gridM.png"));
	private JMenuItem magicInsertSwitch = new JMenuItem("Schalter erzeugen",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "magic-insert-swM.png")));
	private JMenuItem magicInsertLamp = new JMenuItem("Lampen erzeugen",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "magic-insert-laM.png")));
	private JMenuItem doRaster = new JMenuItem("Am Raster ausrichten",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "rasterBM.png")));
	private JMenuItem settings = new JMenuItem("Einstellungen", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "settingsNewM.png")));
	// ------------------------------------------------------------------------

	// JMenuItems fuer den Menuepunkt Ansicht
	// ------------------------------------------------------------------------
	private JMenuItem increase = new JMenuItem("Vergrößern", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "lupe1M.png")));
	private JMenuItem decrease = new JMenuItem("Verkleinern", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "lupe1-M.png")));
	private JMenuItem info = new JMenuItem("Schaltungsinformation",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "info.png")));
	private JMenuItem truthTable = new JMenuItem("Wahrheitstabelle erzeugen",
			new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "tableM.png")));
	// ------------------------------------------------------------------------

	// JMenuItems fuer den Menuepunkt Hilfe
	// ------------------------------------------------------------------------
	private JMenuItem manual = new JMenuItem("Benutzerhandbuch", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "pdf.png")));
	private JMenuItem locsi = new JMenuItem("Über Locsi", new ImageIcon(getClass().getClassLoader().getResource(
			UtilityConstants.ICON_PATH + "author.png")));
	// ------------------------------------------------------------------------

	private EditorModel eModel;
	private TabbedPane tabs;
	private InfoArea infoArea;
	private SimulationModel sModel;

	/**
	 * Dieser Konstruktor erzeugt das <code>MenueBar</code>-Objekt.
	 */
	public MenuBar(EditorModel eModel, SimulationModel sModel, TabbedPane tabs,
			InfoArea infoArea, ExitListener exitListener) {
		this.eModel = eModel;
		this.tabs = tabs;
		this.infoArea = infoArea;
		this.sModel = sModel;

		// Hinzufuegen des Menuepunkts Schaltung samt JMenuItems
		this.add(circuit);
		circuit.add(newC);
		circuit.add(load);
		circuit.add(save);
		circuit.add(export);
		export.add(comp);
		export.add(png);
		export.add(jpeg);
		export.add(gif);
		export.add(bmp);
		export.setIcon(new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.ICON_PATH + "exportM.png")));
		circuit.add(imp);
		circuit.add(exit);

		// Hinzufuegen des Menuepunkts Bearbeiten samt JMenuItems
		this.add(edit);
		edit.add(selectAll);
		edit.add(delete);
		edit.add(check);
		edit.add(magicInsertSwitch);
		edit.add(magicInsertLamp);
		// edit.add(rasterVisible);
		edit.add(doRaster);
		edit.add(new JSeparator());
		edit.add(settings);

		// Hinzufuegen des Menuepunkts Ansicht samt JMenuItems
		this.add(look);
		look.add(increase);
		look.add(decrease);
		look.add(info);
		look.add(truthTable);

		// Hinzufuegen des Menuepunkts Hilfe samt JMenuItems
		this.add(help);
		help.add(manual);
		help.add(locsi);

		initializeJMenus();
		addListener(exitListener, tabs);
	}

	/**
	 * Diese private Methode dient dem Konstruktor als Hilfsmethode. Hier werden
	 * die verschiedenen Tastenkuerzel fuer die einzelnen Eintraege der
	 * <code>MenuBar</code> gesetzt.
	 */
	private void initializeJMenus() {

		// Menuepunkt Schaltung
		newC.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
				Event.CTRL_MASK));
		load.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
				Event.CTRL_MASK));
		save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
				Event.CTRL_MASK));
		comp.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B,
				Event.CTRL_MASK));
		png.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
				Event.CTRL_MASK));
		jpeg.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J,
				Event.CTRL_MASK));
		gif.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,
				Event.CTRL_MASK));
		bmp.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M,
				Event.CTRL_MASK));
		imp.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I,
				Event.CTRL_MASK));
		exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
				Event.CTRL_MASK));

		// Menuepunkt Bearbeiten
		selectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,
				Event.CTRL_MASK));
		delete.setAccelerator(KeyStroke.getKeyStroke("DELETE"));
		check.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,
				Event.CTRL_MASK));
		doRaster.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,
				Event.CTRL_MASK));
		magicInsertSwitch.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,
				Event.CTRL_MASK));
		magicInsertLamp.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
				Event.CTRL_MASK));

		// rasterVisible.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
		// Event.CTRL_MASK));
		settings.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,
				Event.CTRL_MASK));

		// Menuepunkt Ansicht
		increase.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS,
				Event.CTRL_MASK));
		decrease.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS,
				Event.CTRL_MASK));
		info.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L,
				Event.CTRL_MASK));
		truthTable.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
				Event.CTRL_MASK));
		truthTable.setEnabled(false);
		truthTable
				.setToolTipText("Zum Erzeugen der Wahrheitstabelle in Simulationsmodus wechseln");

		// Hilfe
		// keine Shortcuts vorhanden

		// Mnemonics der verschiedenen Menuepunkte
		circuit.setMnemonic('S');
		edit.setMnemonic('B');
		look.setMnemonic('A');
		help.setMnemonic('H');
	}

	/**
	 * Diese private Methode dient dem Konstruktor als Hilfsmethode. Hier werden
	 * die verschiedenen <code>Listener</code> fuer die einzelnen Menuepunkte
	 * gesetzt.
	 */
	private void addListener(ExitListener exitListener, TabbedPane tabs) {

		// Listener Schaltung
		PictureExportListener pel = new PictureExportListener(tabs);
		newC.addActionListener(new NewCircuitListener(eModel));
		load.addActionListener(new LoadCircuitListener(eModel));
		save.addActionListener(new SaveCircuitListener(eModel, infoArea));
		comp.addActionListener(new ComponentExportListener(eModel));
		png.addActionListener(pel);
		jpeg.addActionListener(pel);
		gif.addActionListener(pel);
		bmp.addActionListener(pel);
		imp.addActionListener(new ComponentImportListener(eModel));
		exit.addActionListener(exitListener);

		// Listener Bearbeiten
		selectAll
				.addActionListener(new SelectAllListener(tabs.getEditorArea()));
		delete.addActionListener(new DeleteSelectionListener(tabs
				.getEditorArea(), eModel));
		CheckListener checkListener = new CheckListener(eModel);
		this.tabs.getEditorToolPanel().getCheckButton()
				.addActionListener(checkListener);
		check.addActionListener(checkListener);
		increase.addActionListener(new ZoomInListener(tabs));
		decrease.addActionListener(new ZoomOutListener(tabs));
		info.addActionListener(new CircuitInfoListener(infoArea));
		doRaster.addActionListener(new RasterElementsListener(tabs
				.getEditorArea(), eModel));
		magicInsertSwitch.addActionListener(new AutoCreateSwitchListener(
				eModel, tabs.getEditorArea(), infoArea));
		magicInsertLamp.addActionListener(new AutoCreateLampListener(eModel,
				tabs.getEditorArea(), infoArea));
		// rasterVisible.addActionListener(new SetRasterVisibleListener(tabs
		// .getEditorArea()));
		truthTable.addActionListener(new ShowTruthTableListener(sModel));
		settings.addActionListener(new SettingsListener(tabs));

		// Listener Hilfe
		manual.addActionListener(new UserManualListener());
		locsi.addActionListener(new AboutLocsiListener());
	}

	/**
	 * Mit dieser Methode werden alle Menuepunkte auf False gesetzt, also
	 * ausgeblendet, die nicht im Simulationsmodus zur Verfuegung stehen duerfen
	 */
	public void setSimulationModus() {
		newC.setEnabled(false);
		load.setEnabled(false);
		save.setEnabled(false);
		comp.setEnabled(false);
		imp.setEnabled(false);
		selectAll.setEnabled(false);
		delete.setEnabled(false);
		check.setEnabled(false);
		truthTable.setEnabled(true);
		truthTable.setToolTipText(null);
		magicInsertSwitch.setEnabled(false);
		magicInsertLamp.setEnabled(false);
	}

	/**
	 * Mit dieser Methode werden alle Menuepunkt auf True gesetzt, also einge-
	 * blendet, die im Simulationsmodus nicht zur Verfuegung stehen duerfen,
	 * aber dafuer im Editormodus
	 */
	public void setEditorModus() {
		newC.setEnabled(true);
		load.setEnabled(true);
		save.setEnabled(true);
		comp.setEnabled(true);
		imp.setEnabled(true);
		selectAll.setEnabled(true);
		delete.setEnabled(true);
		check.setEnabled(true);
		truthTable.setEnabled(false);
		truthTable
				.setToolTipText("Zum Erzeugen der Wahrheitstabelle in Simulationsmodus wechseln");
		magicInsertSwitch.setEnabled(true);
		magicInsertLamp.setEnabled(true);
	}
	
	/**
	 * Gibt den 'Wahrheitstabelle erzeugen'-Menueeintrag zurueck
	 * @return
	 */
	public JMenuItem getTruthTableMenuItem() {
		return truthTable;
	}
}